/*
 * Created by SharpDevelop.
 * User: David
 * Date: 2006-11-26
 * Time: 23:33
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

using tools;
using patterns;

using Labb4.Entity;
using Labb4.Media;
using Labb4.Media.Graphics;
using Labb4.Media.Sfx;
using Labb4.Event;
using Labb4.Pooman.Misc;
using Labb4.Pooman.Game;

namespace Labb4.Main
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm
	{
		#region members
		
		private List<IManager>						m_Managers;
		private MediaManager						m_MediaManager = MediaManager.Instance;
		private RenderManager						m_RenderManager = RenderManager.Instance;
		private EntityManager						m_EntityManager = EntityManager.Instance;
		private ControlManager						m_ControlerManager = ControlManager.Instance;
		private EventManager						m_EventManager = EventManager.Instance;
		private Event.EventHandler					m_EventHandler = Event.EventHandler.Instance;
		private FMODManager							m_FMODManager = FMODManager.Instance;
		private TimeManager							m_TimeManager = TimeManager.Instance;
		private InputManager						m_InputManager = InputManager.Instance;
		
		private Properties							m_Settings = Properties.Instance;
		private BufferedGraphicsContext				m_BufferedGraphics;
		
		private PoomanMain							m_PoomanMain;
		private bool								m_Running;
		private string								m_ToolTipString;
		private Point								m_ToolTipLocation;
		
		#endregion
		
		#region static methods
		
		/// <summary>
		/// Starts the application
		/// </summary>
		/// <param name="args">These are not used in this application</param>
		[STAThread]
		public static void Main(string[] args)
		{
			TextWriterTraceListener tr1 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
        	Debug.Listeners.Add(tr1);
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);
			Application.Run(new MainForm());
		}
		
		/// <summary>
		/// Checks the result of an operation done using the dll tools
		/// </summary>
		/// <param name="result"></param>
		/// <returns></returns>
		public static bool ErrorCheck(ToolsResult result)
		{
			bool passed = true;
			
			if(result.Failed)
			{
				passed = false;
				MessageBox.Show(result.Result, result.Header);
				Application.Exit();
			}
			
			return passed;
		}
		
		#endregion
		
		#region constructors
		
		/// <summary>
		/// Constructor of the main form, initializes components and members,
		/// initializes managers, and puts them in the collection m_Managers
		/// </summary>
		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			m_Managers = new List<IManager>();
			
			m_BufferedGraphics = BufferedGraphicsManager.Current;
			UpdateRenderManager(null, null);
			
			m_RenderManager.Initialize();
			m_MediaManager.Initialize();
			m_ControlerManager.Initialize();
			m_EventManager.Initialize();
			m_FMODManager.Initialize();
			m_EntityManager.Initialize();
			m_TimeManager.Initialize();
			m_EventHandler.Initialize();
			
			InitSettings();
			m_PoomanMain = new PoomanMain();
			m_PoomanMain.Initialize();
			
			m_Running = false;
			m_ToolTipString = "";
			m_ToolTipLocation = new Point(0, 0);
			
			m_Managers.Add(m_PoomanMain);
			m_Managers.Add(m_EventHandler);
			m_Managers.Add(m_EventManager);
			m_Managers.Add(m_ControlerManager);
			m_Managers.Add(m_EntityManager);
			m_Managers.Add(m_FMODManager);
			m_Managers.Add(m_RenderManager);
		}
		
		#endregion
		
		#region methods
		
		/// <summary>
		/// The main game thread, the program can not end when this is running
		/// </summary>
		public void RunPoo()
		{
			m_Running = true;
			long lastTime = DateTime.Now.Ticks / 10000;
			long thisTime = 0;
			int deltaTime = 0;
			
			while(!m_InputManager.Quit)
			{
				//update delta time
				thisTime = DateTime.Now.Ticks / 10000;
				deltaTime = (int)(thisTime - lastTime);
				m_TimeManager.Update(ref deltaTime);
				
				//check the menu
				CheckTheMenu();
				
				//update frame
				m_InputManager.StatusString = "";
				m_RenderManager.CLS();
				deltaTime = m_TimeManager.GameDeltaTime;
				Update(ref deltaTime);
				lastTime = thisTime;
				
				//update the status strip
				try
				{
					TheStatusLabel.Text = m_InputManager.StatusString;
				}
				catch(Exception)
				{
				}
				
				//sleep a while
				Thread.Sleep(20);
			}
			
			m_Running = false;
			Application.Exit();
		}
		
		#endregion
		
		#region callbacks
		
		/// <summary>
		/// Sets the graphical references to the render manager. Should be called in the constructor
		/// of a form, and everytime the form changes size.
		/// </summary>
		/// <param name="sender">The object firing this event listener</param>
		/// <param name="e">?</param>
		protected void UpdateRenderManager(object sender, System.EventArgs e)
		{
			Graphics g = this.CreateGraphics();
			BufferedGraphics buff = m_BufferedGraphics.Allocate(g, this.DisplayRectangle);
			m_RenderManager.SetGraphics(g, buff);
		}
		
		/// <summary>
		/// When the mouse moves, we save the new position in the input manager
		/// </summary>
		/// <param name="e">Information about the mouse's whereabouts</param>
		protected override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove(e);
			
			m_InputManager.MouseX = e.X;
			m_InputManager.MouseY = e.Y;
		}
		
		/// <summary>
		/// When the mouse moves over one of the buttons, we have to do some checking up on it
		/// </summary>
		/// <param name="sender">The button the mouse is moving over</param>
		/// <param name="e">Information about the mouse's whereabouts</param>
		protected void OnMouseMoveOverButton(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(m_Settings.ToolTip)
			{
				int x = ((Button)sender).Location.X + ((Button)sender).Width;
				int y = ((Button)sender).Location.Y;
				m_InputManager.MouseX = x;
				m_InputManager.MouseY = y;
				Point thisLocation = new Point(x, y);
				
				if(!thisLocation.Equals(m_ToolTipLocation))
				{
					m_ToolTipLocation = thisLocation;
					TheToolTip.Show(m_ToolTipString, this, m_InputManager.MouseX + 10, m_InputManager.MouseY + 30);
				}
			}
		}
		
		/// <summary>
		/// If a mouse button is being clicked, we want to know which, and save this in the input manager
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseClick(MouseEventArgs e)
		{
			base.OnMouseClick(e);
			
			if(e.Button.ToString().Equals("Left"))
			{
				m_InputManager.MouseClick = true;
			}
		}
		
		/// <summary>
		/// When the form is first started, we start the main thread
		/// </summary>
		/// <param name="e">?</param>
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			
			new Thread(new ThreadStart(RunPoo)).Start();
		}
		
		/// <summary>
		/// If the form wants to close, we have to check that the main thread is not running
		/// </summary>
		/// <param name="sender">The object firing this event</param>
		/// <param name="e">Information about the closing operation</param>
		protected void ClosingDown(object sender, System.Windows.Forms.FormClosingEventArgs e)
		{
			if(m_Running)
			{
				m_InputManager.Quit = true;
				e.Cancel = true;
			}
		}
		
		/// <summary>
		/// Tears all the managers down to free all resources
		/// This is called after the form has been closed
		/// </summary>
		/// <param name="sender">The object firing the event</param>
		/// <param name="e">Information about the closed ?</param>
		protected void TearAllDown(object sender, System.Windows.Forms.FormClosedEventArgs e)
		{
			m_TimeManager.TearDown();
			m_MediaManager.TearDown();
			m_PoomanMain.TearDown();
			
			foreach(IManager it in m_Managers)
			{
				it.TearDown();
			}
		}
		
		/// <summary>
		/// When a button is clicked, this checks which, and stores the buttonclick in the input manager
		/// </summary>
		/// <param name="sender">The object firing the event</param>
		/// <param name="e">Information about the mouse's whereabouts</param>
		protected void Buttons(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(e.Button.ToString().Equals("Left"))
			{
				if(sender == ButtonPlay)
				{
					m_InputManager.PlayCardPressed = true;
				}
				
				if(sender == ButtonChance)
				{
					m_InputManager.ChanceCardPressed = true;
				}
				
				if(sender == ButtonPickup)
				{
					m_InputManager.PickupCardsPressed = true;
				}
			}
		}
		
		/// <summary>
		/// Handles events fired from the menun, and stores the information in the input manager
		/// </summary>
		/// <param name="sender">The object firing the event</param>
		/// <param name="e">?</param>
		protected void MenuEventHandler(object sender, System.EventArgs e)
		{
			if(sender == FileNew)
			{
				if(m_Running)
				{
					m_InputManager.FileNew = true;
				}
				else
				{
					RunPoo();
				}
			}
			
			if(sender == FileOpen)
			{
				OpenFileDialog open = new OpenFileDialog();
				open.Filter = "Pooman game files (*.pgf)|*.pgf";
				open.Title = "Select a Pooman Game File to load!";
				
				if(open.ShowDialog(this) != DialogResult.Cancel)
				{
					if(System.IO.File.Exists(open.FileName))
					{
						m_InputManager.FileName = open.FileName;
						m_InputManager.FileOpen = true;
					}
				}
			}
			
			if(sender == FileSave)
			{
				SaveFileDialog save = new SaveFileDialog();
				save.Filter = "Pooman game files (*.pgf)|*.pgf";
				save.Title = "Save your current game!";
				
				if(save.ShowDialog(this) != DialogResult.Cancel)
				{
					m_InputManager.FileName = save.FileName;
					m_InputManager.FileSave = true;
				}
			}
			
			if(sender == FileSettings)
			{
				SettingsForm settingsForm = new SettingsForm();
				settingsForm.Show();
			}
			
			if(sender == FileExit)
			{
				m_InputManager.Quit = true;
			}
			
			if(sender == HelpHelp)
			{
				Process.Start(m_Settings.StartPath + "resources\\help\\POOMAN.HLP");
			}
			
			if(sender == HelpAbout)
			{
				MessageBox.Show("                        Pooman version 1.0, created by David Wallin\n" +
				                "     Based on a traditional Swedish card game, best played by three players     \n" +
				                "                 For help, press F1, or choose Help from the Help menu\n" +
				                "\n" +
				                "                            Developed in SharpDevelop 2006/2007"
				                
				                ,"About Pooman");
			}
		}
		
		/// <summary>
		/// Draws a tooltip to the screen
		/// </summary>
		/// <param name="sender">The object firing the event</param>
		/// <param name="e">?</param>
		protected void ToolTipActivate(object sender, System.EventArgs e)
		{
			if(sender == ButtonChance)
			{
				m_ToolTipString = "Click to play the top card in the deck, on\nchance. Might be good, might be bad. Only\nworks in phase 1";
			}
			
			if(sender == ButtonPlay)
			{
				m_ToolTipString = "Click to play the cards you have selected.";
			}
			
			if(sender == ButtonPickup)
			{
				m_ToolTipString = "Click to pick up the bottom most card(s).\nOnly works in phase 2.";
			}
		}
		
		/// <summary>
		/// Deactivates, or hides, the tooltip
		/// </summary>
		/// <param name="sender">The object firing the event</param>
		/// <param name="e">?</param>
		protected void ToolTipDeactivate(object sender, System.EventArgs e)
		{
			TheToolTip.Hide(this);
		}
		
		#endregion
		
		#region protected methods
		
		/// <summary>
		/// Initializes the settings of the game through reading them from a file
		/// </summary>
		protected void InitSettings()
		{
			Config config = new Config();
			
			if(ErrorCheck(config.Open(m_Settings.StartPath + "resources\\configfiles\\settings.txt")))
			{
				bool debug = false;
				bool openCards = false;
				bool muteAudio = false;
				bool helpBubbles = false;
				int displayTime = 0;
				
				if(ErrorCheck(config.GetBool("debug", ref debug)) &&
				   ErrorCheck(config.GetBool("open_cards", ref openCards)) &&
				   ErrorCheck(config.GetBool("mute_audio", ref muteAudio)) &&
				   ErrorCheck(config.GetBool("help_bubbles", ref helpBubbles)) &&
				   ErrorCheck(config.GetInt("display_time", ref displayTime)))
				{
					Properties.Instance.Debug = debug;
					Properties.Instance.DisplayTimeForWonCards = displayTime;
					Properties.Instance.MuteAudio = muteAudio;
					Properties.Instance.OpenCards = openCards;
					Properties.Instance.ToolTip = helpBubbles;
				}
			}
		}
		
		#endregion
		
		#region private methods
		
		/// <summary>
		/// Updates all the managers in the collection m_Managers
		/// </summary>
		/// <param name="deltaTime"></param>
		private void Update(ref int deltaTime)
		{
			foreach(IManager it in m_Managers)
			{
				it.Update(ref deltaTime);
			}
		}
		
		/// <summary>
		/// Checks the input from the menu
		/// </summary>
		private void CheckTheMenu()
		{
			if(m_InputManager.FileOpen)
			{
				m_PoomanMain.ResetGame(m_InputManager.FileName);
			}
			
			if(m_InputManager.FileSave)
			{
				m_PoomanMain.SaveGame(m_InputManager.FileName);
			}
			
			if(m_InputManager.FileNew)
			{
				m_PoomanMain.ResetGame();
			}
		}
		
		#endregion
	}
}
